package cn.edu.nju.software.greencreditsystem.business;

import cn.edu.nju.software.greencreditsystem.DAO.*;
import cn.edu.nju.software.greencreditsystem.domain.*;
import cn.edu.nju.software.greencreditsystem.factory.DAOFactory;
import java.io.*;
import java.sql.Date;

/**
 * 作者：何启睿
 * 创建时间：2011-8-19
 * 类描述：处理通过审核的财务报表的静态工具类
 */
public class FinancialHandler
{
    /**
     * 方法描述：传入已审核的财务报表，分析后生成财务评分、预警、警告记录存入数据库
     * param：xml文件，FinancialExcel对象，企业
     * return：是否成功
    */
    public static boolean handle(String xmlPath, FinancialExcel fe, int enterpriseID)
    {
        boolean result = false;
        
        String excelPath = "temp" + System.currentTimeMillis() + ".xls";
        File excelFile = new File(excelPath);
        FinancialAnalyser analyser = new WoleAnalyser();
        FinancialPredictor predictor = new LogisticPredictor();
        EnterpriseDAO edao = DAOFactory.getEnterpriseDAOInstance();
        EnvironmentScoreDAO esdao = DAOFactory.getEnvironmentScoreDAOInstance();
        FinancialFactorDAO ffdao = DAOFactory.getFinancialFactorDAOInstance();
        FinancialScoreDAO fsdao = DAOFactory.getFinancialScoreDAOInstance();
        FinancialStandardValueDAO fsvdao = DAOFactory.getFinancialStandardValueDAOInstance();
        FinancialWarningDAO fwdao = DAOFactory.getFinancialWarningDAOInstance();
        FinancialWarningTypeDAO fwtdao = DAOFactory.getFinancialWarningTypeDAOInstance();
        LogisticHistoryDAO lhdao = DAOFactory.getLogisticHistoryDAOInstance();
        PredictionDAO pdao = DAOFactory.getPredictionDAOInstance();
        SystemConstantDAO scdao= DAOFactory.getSystemConstantDAOInstance();
        WarningTemplateDAO wtdao = DAOFactory.getWarningTemplateDAOInstance();
        Date today = fe.getSubmitDate();
        
        
        try
        {
            FileOutputStream out = new FileOutputStream(excelFile);
            out.write(fe.getData());
            out.close();
            
            //分析数据并保存财务指标历史记录和警告历史记录
            double indexs[] = analyser.getIndex(xmlPath, excelPath);
            FinancialStandardValue standardValues[] = fsvdao.getStandardValueObjects();
            FinancialStandardValue changeValues[] = fsvdao.getChangeValueObjects();
            for(int i = 0; i < indexs.length; i++)
            {
                FinancialFactor fftemp = ffdao.getByName(WoleAnalyser.factorNames[i]);
                        
                FinancialScore fs = new FinancialScore();
                fs.setDate(fe.getDeadline());
                fs.setEnterprise(edao.getById(enterpriseID));
                fs.setFactor(fftemp);
                fs.setValue(indexs[i]);
                fsdao.save(fs);
                
                //若大（小）于标准值则生成警告
                if((standardValues[i].getLargeBetter() && (standardValues[i].getValue() > fs.getValue()))
                        || (!standardValues[i].getLargeBetter() && (standardValues[i].getValue() < fs.getValue())))
                {
                    FinancialWarning fw = new FinancialWarning();
                    
                    FinancialWarningType fwt = new FinancialWarningType();
                    fwt.setFactor(fftemp);
                    fwt.setType(FinancialWarningType.STANDARD);
                    fwt.setValue(fs.getValue());
                    
                    fw.setBankReaded(false);
                    fw.setDate(today);
                    fw.setEnterprise(edao.getById(enterpriseID));
                    fw.setEnterpriseReaded(false);
                    fw.setType(fwt);
                    fw.setWarningTemplate(wtdao.getById((int) scdao.get("currentWarningTemplate")));
                    
                    fwtdao.save(fwt);
                    fwdao.save(fw);
                }
                
                //若变动幅大于最大允许变动幅则生成警告
                double changeValue = fsdao.getIncreaseMargin(enterpriseID, fftemp.getId());
                if(Math.abs(changeValue) >= changeValues[i].getValue())
                {
                    FinancialWarning fw = new FinancialWarning();
                    
                    FinancialWarningType fwt = new FinancialWarningType();
                    fwt.setFactor(fftemp);
                    fwt.setType(FinancialWarningType.CHANGE);
                    fwt.setValue(changeValue);
                    
                    fw.setBankReaded(false);
                    fw.setDate(today);
                    fw.setEnterprise(edao.getById(enterpriseID));
                    fw.setEnterpriseReaded(false);
                    fw.setType(fwt);
                    fw.setWarningTemplate(wtdao.getById((int) scdao.get("currentWarningTemplate")));
                    
                    fwtdao.save(fwt);
                    fwdao.save(fw);
                }
            }
            
            //保存预警历史记录，破产概率大于0.5则标记为未读
            predictor.init(scdao.get("leastLogisticCor"));
            double p = predictor.estimate(lhdao.getEstimateParameter(enterpriseID, today));
            Prediction prediction = new Prediction();
            prediction.setDate(today);
            prediction.setEnterprise(edao.getById(enterpriseID));
            prediction.setProbability(p);
            if(p >= 0.5)
                prediction.setReaded(false);
            else
                prediction.setReaded(true);
            
            pdao.save(prediction);
            predictor.end();
            
            //更新企业等级评定
            Enterprise e = edao.getById(enterpriseID);
            double score = ((fsdao.getLatestTotalScore(enterpriseID) * scdao.get("financialWeight"))
                            + (esdao.getLatestTotalScore(enterpriseID) * scdao.get("environmentWeight"))) / 100;
            if(score < scdao.get("oneStar"))
                e.setLevel(1);
            else if(score < scdao.get("twoStar"))
                e.setLevel(2);
            else if(score < scdao.get("threeStar"))
                e.setLevel(3);
            else if(score < scdao.get("fourStar"))
                e.setLevel(4);
            else
                e.setLevel(5);
            edao.update(e);
            
            result = true;
        } catch (Exception ex)
        {
            ex.printStackTrace();
        }finally
        {
            excelFile.delete();;
        }
        
        return result;
    }
}
